#ifndef		__PINFUN_H
#define		__PINFUN_H

#include "NuMicro.h"

/*******************************************************************************
* @brief   io mode
*******************************************************************************/
__STATIC_INLINE void gpio_mode_set(GPIO_T *port, uint32_t pos, uint32_t u32Mode)
{
    port->MODE = (port->MODE & ~(0x3ul << (pos << 1))) | (u32Mode << (pos << 1));
}


/*******************************************************************************
* @brief   方向
*******************************************************************************/
void bsp_gpio_mode_out_pp(GPIO_T * port, uint8_t pin);
void bsp_gpio_mode_out_od(GPIO_T * port, uint8_t pin);
void bsp_gpio_mode_in_up(GPIO_T * port, uint8_t pin);
void bsp_gpio_mode_in_dn(GPIO_T * port, uint8_t pin);
void bsp_gpio_mode_in_ft(GPIO_T * port, uint8_t pin);

/*******************************************************************************
* @brief   同相IO定义
*******************************************************************************/
typedef struct
{
    void(*en)(void);
    void(*dis)(void);
    void(*tog)(void);
    uint8_t(*out_st)(void);
    uint8_t(*in_st)(void);
    void(*dir_in_ft)(void);		//浮空输入
    void(*dir_in_up)(void);		//上拉输入
    void(*dir_out_pp)(void);	//推挽输出
    void(*dir_out_od)(void);	//开漏输出
} port_io_pin_type;

#ifndef PORT_PIN_CTEAT
#define port_io_pin_make(name, port, pin)						\
extern const port_io_pin_type name
#else   
#define port_io_pin_make(name, port, pin)						\
void name##_pin_en(void){port##pin=1;}							\
void name##_pin_dis(void){port##pin=0;}							\
void name##_pin_tog(void){port##pin=!port##pin;}				\
uint8_t name##_pin_out_st(void){return port##pin;}				\
uint8_t name##_pin_in_st(void){return port##pin;}				\
void name##_dir_in_ft(void){bsp_gpio_mode_in_ft(port, pin);}	\
void name##_dir_in_up(void){bsp_gpio_mode_in_up(port, pin);}	\
void name##_dir_out_pp(void){bsp_gpio_mode_out_pp(port, pin);}	\
void name##_dir_out_od(void){bsp_gpio_mode_out_od(port, pin);}	\
const port_io_pin_type name = {	\
    name##_pin_en,				\
    name##_pin_dis,				\
    name##_pin_tog,				\
    name##_pin_out_st,			\
    name##_pin_in_st,			\
    name##_dir_in_ft,			\
    name##_dir_in_up,			\
    name##_dir_out_pp,			\
    name##_dir_out_od			\
}
#endif

/*******************************************************************************
* @brief   反相IO定义
*******************************************************************************/
#ifndef PORT_PIN_CTEAT
#define port_nio_pin_make(name, port, pin)						\
extern const port_io_pin_type name
#else   
#define port_nio_pin_make(name, port, pin)						\
void name##_pin_en(void){port##pin=0;}							\
void name##_pin_dis(void){port##pin=1;}							\
void name##_pin_tog(void){port##pin=!port##pin;}				\
uint8_t name##_pin_out_st(void){return !port##pin;}				\
uint8_t name##_pin_in_st(void){return !port##in(pin);}			\
void name##_dir_in_ft(void){bsp_gpio_mode_in_ft(port, pin);}	\
void name##_dir_in_up(void){bsp_gpio_mode_in_up(port, pin);}	\
void name##_dir_out_pp(void){bsp_gpio_mode_out_pp(port, pin);}	\
void name##_dir_out_od(void){bsp_gpio_mode_out_od(port, pin);}	\
const port_io_pin_type name = {	\
    name##_pin_en,				\
    name##_pin_dis,				\
    name##_pin_tog,				\
    name##_pin_out_st,			\
    name##_pin_in_st,			\
    name##_dir_in_ft,			\
    name##_dir_in_up,			\
    name##_dir_out_pp,			\
    name##_dir_out_od			\
}
#endif

/*******************************************************************************
* @brief   同相OUT定义
*******************************************************************************/
typedef struct
{
    void(*en)(void);
    void(*dis)(void);
    void(*tog)(void);
    uint8_t(*out_st)(void);
    void(*dir_out_pp)(void);	//推挽输出
    void(*dir_out_od)(void);	//开漏输出
} port_out_pin_type;

#ifndef PORT_PIN_CTEAT
#define port_out_pin_make(name, port, pin)						\
extern const port_out_pin_type name
#else   
#define port_out_pin_make(name, port, pin)						\
void name##_pin_en(void){port##pin=1;}							\
void name##_pin_dis(void){port##pin=0;}							\
void name##_pin_tog(void){port##pin=!port##pin;}				\
uint8_t name##_pin_out_st(void){return port##pin;}				\
void name##_dir_out_pp(void){bsp_gpio_mode_out_pp(port, pin);}	\
void name##_dir_out_od(void){bsp_gpio_mode_out_od(port, pin);}	\
const port_out_pin_type name = {	\
    name##_pin_en,				\
    name##_pin_dis,				\
    name##_pin_tog,				\
    name##_pin_out_st,			\
    name##_dir_out_pp,			\
    name##_dir_out_od			\
}
#endif

/*******************************************************************************
* @brief   反相OUT定义
*******************************************************************************/
#ifndef PORT_PIN_CTEAT
#define port_nout_pin_make(name, port, pin)						\
extern const port_out_pin_type name
#else   
#define port_nout_pin_make(name, port, pin)						\
void name##_pin_en(void){port##pin=0;}							\
void name##_pin_dis(void){port##pin=1;}							\
void name##_pin_tog(void){port##pin=!port##pin;}				\
uint8_t name##_pin_out_st(void){return !port##pin;}				\
void name##_dir_out_pp(void){bsp_gpio_mode_out_pp(port, pin);}	\
void name##_dir_out_od(void){bsp_gpio_mode_out_od(port, pin);}	\
const port_out_pin_type name = {	\
    name##_pin_en,				\
    name##_pin_dis,				\
    name##_pin_tog,				\
    name##_pin_out_st,			\
    name##_dir_out_pp,			\
    name##_dir_out_od			\
}
#endif

/*******************************************************************************
* @brief   同相IN定义
*******************************************************************************/
typedef struct
{
    uint8_t(*in_st)(void);
    void(*dir_in_ft)(void);		//浮空输入
    void(*dir_in_up)(void);		//上拉输入
    void(*dir_in_dn)(void);		//下拉输入
} port_in_pin_type;

#ifndef PORT_PIN_CTEAT
#define port_in_pin_make(name, port, pin)							\
extern const port_in_pin_type name
#else   
#define port_in_pin_make(name, port, pin)							\
uint8_t name##_pin_in_st(void){return port##in(pin);}				\
void name##_dir_in_ft(void){bsp_gpio_mode_in_ft(port, pin);}		\
void name##_dir_in_up(void){bsp_gpio_mode_in_up(port, pin);}		\
void name##_dir_in_dn(void){bsp_gpio_mode_in_dn(port, pin);}		\
const port_in_pin_type name = {	\
    name##_pin_in_st,			\
    name##_dir_in_ft,			\
    name##_dir_in_up,			\
    name##_dir_in_dn,			\
}
#endif

/*******************************************************************************
* @brief   反相IN定义
*******************************************************************************/
#ifndef PORT_PIN_CTEAT
#define port_nin_pin_make(name, port, pin)							\
extern const port_in_pin_type name
#else   
#define port_nin_pin_make(name, port, pin)							\
uint8_t name##_pin_in_st(void){return !port##in(pin);}				\
void name##_dir_in_ft(void){bsp_gpio_mode_in_ft(port, pin);}		\
void name##_dir_in_up(void){bsp_gpio_mode_in_up(port, pin);}		\
void name##_dir_in_dn(void){bsp_gpio_mode_in_dn(port, pin);}		\
const port_in_pin_type name = {	\
    name##_pin_in_st,			\
    name##_dir_in_ft,			\
    name##_dir_in_up,			\
    name##_dir_in_dn,			\
}
#endif

#endif
